package wang.java.util;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class ProcessRunner {
    public static final boolean isLinux = System.getProperty("file.separator").equals("/");
    public static final String commandPrefix = isLinux ? "sh" : "cmd";
    public static final String prefixParam = isLinux ? "-c" : "/c";
    private static final String SYSTEM_CHARSET = System.getProperty("sun.jnu.encoding");

    private List<String> outputList = new ArrayList<>();
    private List<String> errorList = new ArrayList<>();

    public List<String> getOutputList() {
        return outputList;
    }

    public List<String> getErrorList() {
        return errorList;
    }

    public int run(String command, boolean checkExitCode) {
        return run(command, checkExitCode, null, false);
    }

    /**
     * @param command
     * @param checkExitCode
     * @return
     */
    public int run(String command, boolean checkExitCode, File dir, boolean silent) {
        outputList.clear();
        errorList.clear();
        Runtime runtime = Runtime.getRuntime();
        Process process = null;
        Integer exitCode = null;
        try {
            System.out.println(command);
            process = runtime.exec(new String[]{commandPrefix, prefixParam, command}, null, dir);
            InputStream in;
            try (BufferedReader inputReader = new BufferedReader(new InputStreamReader(process.getInputStream(), SYSTEM_CHARSET));
                 BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream(), SYSTEM_CHARSET))) {
                String outputLine = null;
                String errLine = null;

                while (Objects.nonNull(outputLine = inputReader.readLine()) || Objects.nonNull(errLine = errorReader.readLine())) {
                    if (Objects.nonNull(outputLine)) {
                        if (!silent) {
                            System.out.println(outputLine);
                        }
                        outputList.add(outputLine);
                    }

                    if (Objects.nonNull(errLine)) {
                        System.err.println(errLine);
                        errorList.add(errLine);
                    }
                }
            } catch (RuntimeException e) {
                e.printStackTrace();
            }

            exitCode = process.waitFor();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (RuntimeException e) {
            e.printStackTrace();
        } finally {
            process.destroy();
        }

        if (checkExitCode && !Objects.equals(0, exitCode)) {
            throw new RuntimeException("命令执行异常，返回码为:" + exitCode);
        }
        return exitCode;
    }

}
